/*
 * SysUtil.c
 *
 *  Created on: 2011-7-9
 *      Author: gexiao
 */
#include "SysUtil.h"

#include <unistd.h>
#include <sys/mman.h>
#include <assert.h>

static int getFileStartAndLength(int fd, off_t *start_, size_t *length_) {
	off_t start, end;
	size_t length;

	start = lseek(fd, 0L, SEEK_CUR);
	end = lseek(fd, 0L, SEEK_END);
	(void) lseek(fd, start, SEEK_SET);

	if (start == (off_t) -1 || end == (off_t) -1)
		return -1;

	length = end - start;

	if (length == 0)
		return 0;

	*start_ = start;
	*length_ = length;

	return 0;
}

/*
 * Map a file (from fd's current offset) into a shared, read-only memory
 * segment. The file offset must be a multiple of the page size.
 *
 * On success, returns 0 and fills out "pMap". On failure, returns a nonzero
 * value and does not disturb "pMap"
 */
int sysMapFileSegmentInShmem(int fd, off_t start, size_t length,
		MemMapping* pMap) {
	size_t actualLength;
	off_t actualStart;
	int adjust;
	void* memPtr;

	assert(pMap != NULL);

	/* adjust to be page-aligned */
	adjust = start % SYSTEM_PAGE_SIZE;
	actualStart = start - adjust;
	actualLength = length + adjust;

	memPtr = mmap(NULL, actualLength, PROT_READ, MAP_FILE | MAP_SHARED, fd,
			actualStart);
	if (memPtr == MAP_FAILED) {
		//LOGW("mmap(%d, R, FILE|SHARED, %d, %d) failed: %s\n",
		//	(int) actualLength, fd, (int) actualStart, strerror(errno));
		return -1;
	}

	pMap->baseAddr = memPtr;
	pMap->baseLength = actualLength;
	pMap->addr = (char*) memPtr + adjust;
	pMap->length = length;

	//LOGVV("mmap seg (st=%d ln=%d): bp=%p bl=%d ad=%p ln=%d\n", (int) start,
	//	(int) length, pMap->baseAddr, (int) pMap->baseLength, pMap->addr,
	//(int) pMap->length);

	return 0;
}

/*
 * Release a memory mapping.
 */
void sysReleaseShmem(MemMapping* pMap) {
	if (pMap->baseAddr == NULL && pMap->baseLength == 0)
		return;
	if (munmap(pMap->baseAddr, pMap->baseLength) < 0) {
	} else {
		pMap->baseAddr = NULL;
		pMap->baseLength = 0;
	}
}

/*
 * Make a copy of a MemMapping.
 */
void sysCopyMap(MemMapping* dst, const MemMapping* src) {
	memcpy(dst, src, sizeof(MemMapping));
}
